package org.sqlproc.engine.impl;

import java.util.ArrayList;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.sqlproc.engine.SqlFeature;

/**
 * A META SQL sub-element.
 * 
 * <p>
 * Schematically:
 * 
 * <pre>
 * SqlMetaAndOrItem
 *     SqlMetaText
 *     SqlMetaIdent
 *     SqlMetaConst
 * </pre>
 * 
 * @author <a href="mailto:Vladimir.Hudec@gmail.com">Vladimir Hudec</a>
 */
class SqlMetaAndOrItem implements SqlMetaElement {

    /**
     * The internal slf4j logger.
     */
    final Logger logger = LoggerFactory.getLogger(getClass());

    /**
     * The list of sub-elements based on ANTLR grammar.
     */
    List<SqlMetaSimple> elements;

    /**
     * Creates a new instance. It's used from inside ANTLR parser.
     */
    SqlMetaAndOrItem() {
        this.elements = new ArrayList<SqlMetaSimple>();
    }

    /**
     * Adds a new sub-element. It's used from inside ANTLR parser.
     * 
     * @param element
     *            new sub-element, based on ANTLR grammar
     */
    void addElement(SqlMetaSimple element) {
        elements.add(element);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public SqlProcessResult process(SqlProcessContext ctx) {
        SqlProcessResult result = new SqlProcessResult();
        result.addTrue();
        StringBuilder s = new StringBuilder();
        result.setSql(s);
        boolean like = false;
        for (SqlMetaSimple item : this.elements) {
            SqlProcessResult itemResult = item.process(ctx);
            if (logger.isDebugEnabled())
                logger.debug("DataAndItem process " + item.getClass() + " " + item + " " + itemResult);
            if (itemResult.isAdd()) {
                s.append(itemResult.getSql());
                result.addInputValues(itemResult.getInputValues());
                if (logger.isDebugEnabled())
                    logger.debug("DataAndItem process, add " + itemResult.getSql() + " " + itemResult.getInputValues());
                if (ctx.isFeature(SqlFeature.SURROUND_QUERY_LIKE) && item instanceof SqlMetaIdent && like) {
                    for (String ident : itemResult.getInputValues().keySet()) {
                        itemResult
                                .getInputValues()
                                .get(ident)
                                .setLike(ctx.getFeature(SqlFeature.WILDCARD_CHARACTER),
                                        ctx.getFeatureAsInt(SqlFeature.SURROUND_QUERY_MIN_LEN));
                    }
                } else if (item instanceof SqlMetaText
                        && ctx.isFeature(SqlFeature.SURROUND_QUERY_LIKE)
                        && itemResult.getSql().toString().trim().toLowerCase()
                                .endsWith(ctx.getFeature(SqlFeature.LIKE_STRING))) {
                    like = true;
                } else
                    like = false;
            } else
                result.addFalse();
        }
        return result;
    }
}
